﻿/************************************/
/***** Custom E-Mail Component  *****/
/* Author: Krishna C. Mukherjee     */
/* Date:   February, 2014           */
/************************************/

using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Net;
using System.Net.Mail;
using System.Threading;
using System.IO;
using MailMessage = System.Net.Mail.MailMessage;

namespace EmailComponent
{
    public partial class Email : Component
    {
        #region Private Variables Declaration

        private string m_MailFrom;
        private List<string> m_MailTo;
        private string m_MailSubject;
        private string m_MailBody;
        private string m_SMTPServer;
        private int m_SMTPPort;
        private string m_SMTPUsername;
        private string m_SMTPPassword;
        private bool m_SMTPSSL;
        private bool m_SendAsync;
        private bool m_RetryOnFailure;
        private int m_RetryDelayTime;
        private string[] m_MailAttachments;
        private AlternateViewCollection m_ImageObjects;
        private string m_ErrorMsg;
        private bool m_IsBodyHTML;

        #endregion

        #region Public Properties

        public string MailFrom
        {
            set
            {
                m_MailFrom = value;
            }
            get
            {
                return m_MailFrom;
            }
        }

        public List<string> MailTo
        {
            set
            {
                m_MailTo = value;
            }
            get
            {
                return m_MailTo;
            }
        }

        public string MailSubject
        {
            set
            {
                m_MailSubject = value;
            }
            get
            {
                return m_MailSubject;
            }
        }

        public string MailBody
        {
            set
            {
                m_MailBody = value;
            }
            get
            {
                return m_MailBody;
            }
        }

        public string SMTPServer
        {
            set
            {
                m_SMTPServer = value;
            }
            get
            {
                return m_SMTPServer;
            }
        }

        public int SMTPPort
        {
            set
            {
                m_SMTPPort = value;
            }
            get
            {
                return m_SMTPPort;
            }
        }

        public string SMTPUsername
        {
            set
            {
                m_SMTPUsername = value;
            }
            get
            {
                return m_SMTPUsername;
            }
        }

        public string SMTPPassword
        {
            set
            {
                m_SMTPPassword = value;
            }
            get
            {
                return m_SMTPPassword;
            }
        }

        public bool SMTPSSL
        {
            set
            {
                m_SMTPSSL = value;
            }
            get
            {
                return m_SMTPSSL;
            }
        }

        public bool SendAsync
        {
            set
            {
                m_SendAsync = value;
            }
            get
            {
                return m_SendAsync;
            }
        }

        public bool RetryOnFailure
        {
            set
            {
                m_RetryOnFailure = value;
            }
            get
            {
                return m_RetryOnFailure;
            }
        }

        public int RetryDelayTime
        {
            set
            {
                m_RetryDelayTime = value;
            }
            get
            {
                return m_RetryDelayTime;
            }
        }

        public string[] MailAttachments
        {
            set
            {
                m_MailAttachments = value;
            }
            get
            {
                return m_MailAttachments;
            }
        }

        public string ErrorMsg
        {
            set
            {
                m_ErrorMsg = value;
            }
            get
            {
                return m_ErrorMsg;
            }
        }

        public bool IsBodyHTML
        {
            set
            {
                m_IsBodyHTML = value;
            }
            get
            {
                return m_IsBodyHTML;
            }
        }

        public AlternateViewCollection ImageObjects
        {
            set
            {
                m_ImageObjects = value;
            }
            get
            {
                return m_ImageObjects;
            }
        }

        #endregion

        #region Constructor and Intialization

        public Email()
        {
            InitializeComponent();

            // Default values
            m_MailFrom = "";
            m_MailTo = new List<string>();
            m_MailSubject = "";
            m_MailBody = "";
            m_SMTPServer = "";
            m_SMTPPort = 25;
            m_SMTPUsername = "";
            m_SMTPPassword = "";
            m_SMTPSSL = false;
            m_SendAsync = false;
            m_RetryOnFailure = true;
            m_RetryDelayTime = 10000;
            m_MailAttachments = new string[1];
        }

        public Email(IContainer container)
        {
            container.Add(this);
            InitializeComponent();
        }

        #endregion

        #region Public Functions

        public Boolean Send()
        {
            // Construct the email message
            MailMessage Email = new MailMessage();
            MailAddress MailFrom = new MailAddress(m_SMTPUsername, m_MailFrom);
            Email.From = MailFrom;

            foreach (string email_id in m_MailTo)
            {
                Email.To.Add(email_id);
            }

            Email.Subject = m_MailSubject;
            Email.Body = m_MailBody;
            Email.IsBodyHtml = IsBodyHTML;

            for (int idxMailAttachment = 0; idxMailAttachment < MailAttachments.Length; idxMailAttachment++)
            {
                if (File.Exists(MailAttachments[idxMailAttachment]))
                {
                    Attachment mailAttachment = new Attachment(MailAttachments[idxMailAttachment]);
                    Email.Attachments.Add(mailAttachment);
                }
            }

            if (ImageObjects != null)
            {
                foreach (AlternateView imageObject in ImageObjects)
                {
                    Email.AlternateViews.Add(imageObject);
                }
            }

            // Create the client
            SmtpClient SmtpMail = new SmtpClient(m_SMTPServer, m_SMTPPort);
            SmtpMail.Credentials = new NetworkCredential(m_SMTPUsername, m_SMTPPassword);
            SmtpMail.EnableSsl = m_SMTPSSL;

            SmtpMail.SendCompleted += new SendCompletedEventHandler(this.SendCompleted);

            Boolean success = true;

            try
            {
                if (m_SendAsync)
                    SmtpMail.SendAsync(Email, "");
                else
                    SmtpMail.Send(Email);
            }
            catch (SmtpFailedRecipientsException e)
            {
                success = false;

                for (int idxException = 0; idxException < e.InnerExceptions.Length; idxException++)
                {
                    SmtpStatusCode StatusCode = e.InnerExceptions[idxException].StatusCode;
                    if (StatusCode == SmtpStatusCode.MailboxUnavailable || StatusCode == SmtpStatusCode.MailboxBusy)
                    {
                        try
                        {
                            if (m_RetryOnFailure)
                            {
                                Thread.Sleep(m_RetryDelayTime);

                                // Send the message
                                if (m_SendAsync)
                                    SmtpMail.SendAsync(Email, "");
                                else
                                    SmtpMail.Send(Email);

                                // Message was sent
                                success = true;
                            }
                        }
                        catch
                        {
                            // Message could not be sent
                            success = false;
                        }
                    }
                }
            }

            return success;
        }

        public void SendCompleted(object sender, AsyncCompletedEventArgs e)
        {
            MailMessage mailMessage = (MailMessage)e.UserState;
            string subject = mailMessage.Subject;

            if (e.Cancelled)
            {
                string cancelled = string.Format("[{0}] Send Canceled.", subject);
                ErrorMsg = "Canceled";
            }
            if (e.Error != null)
            {
                ErrorMsg = String.Format("[{0}] {1}", subject, e.Error.ToString());
            }
            else
            {
                ErrorMsg = "Message Sent.";
            }
        }

        #endregion
    }
}



